package com.yangfan.screenshot.log;

import android.os.Handler;
import android.os.HandlerThread;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;

/**
 * @author : yangfan_rj
 * @date   : 2022/12/7-14:16
 * desc   :
 */
public class FileLogger implements ILogger {

    private String TAG = "FileLogger";

    private String mLogDirPath;

    private HandlerThread mLogThread;

    private Handler mLogHandler;

    private FileWriter mFileWriter;

    private File mLogFile;

    private static int MAX_LOG_FILE_NUM = 10;

    private static int MAX_LOG_FILE_SIZE = 10 * 1024 * 1024;

    private static int DEFAULT_LOG_FILE_PERIOD = 24 * 60 * 60 * 1000;

    private final SimpleDateFormat mFileDateFormat = new SimpleDateFormat("yyyy-MM-dd_HH_mm_ss");
    private final SimpleDateFormat mLogFormat = new SimpleDateFormat("MM-dd_HH_mm_ss.SS");


    public FileLogger(String logDirPath) {
        mLogDirPath = logDirPath;
        mLogThread = new HandlerThread(TAG);
        mLogThread.start();
        mLogHandler = new Handler(mLogThread.getLooper());
    }

    private void writeToLogFile(String log) throws IOException {
        if (mFileWriter == null) {
            mLogFile = getLogFile();
            if (mLogFile == null) return;
            mFileWriter = new FileWriter(mLogFile, true);
        }
        mFileWriter.write(log);
        mFileWriter.flush();
        if (mLogFile != null && mLogFile.length() >= MAX_LOG_FILE_SIZE) mFileWriter = null;
    }

    private boolean canWriteTo(File targetFile) {
        long fileCreateTime = 0;
        String fileName = targetFile.getName().substring(0, targetFile.getName().length() - 4);
        try {
            Date date = mFileDateFormat.parse(fileName);
            fileCreateTime = date.getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        if (fileCreateTime > 0 && (new Date().getTime()  - fileCreateTime < DEFAULT_LOG_FILE_PERIOD)) {
            if (targetFile.length() < MAX_LOG_FILE_SIZE) return true;
        }
        return false;
    }

    private File getLogFile() {
        File logDir = new File(mLogDirPath);
        if (!logDir.exists()) {
            logDir.mkdirs();
        }
        File[] files = logDir.listFiles();
        if (files != null && files.length != 0) {
            Arrays.sort(files, mFileComparator);
            File lastFile = files[0];
            if (canWriteTo(lastFile)) {
                return lastFile;
            }
            checkLogFileNum(files);
        }
        return newLogFile();
    }

    private File newLogFile() {

        mLogFile = new File(mLogDirPath + mFileDateFormat.format(new Date()) + ".txt");
        try {
            mLogFile.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
        return mLogFile;
    }

    private void checkLogFileNum(File[] logFiles) {
        if (logFiles != null && logFiles.length >= MAX_LOG_FILE_NUM) {
            logFiles[0].delete();
        }
    }

    private Comparator<File> mFileComparator = new Comparator<File>() {
        public int compare(File f1, File f2) {
            return (int) (f2.lastModified() - f1.lastModified());
        }
    };

    @Override
    public void wtf(final String tag, final String message) {

        mLogHandler.post(new Runnable() {
            @Override
            public void run() {
                try {
                    String log = mLogFormat.format(new Date()) + " WTF" + "/" + tag + ":" + message + "\n";
                    writeToLogFile(log);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    public void d(final String tag, final String message) {
        mLogHandler.post(new Runnable() {
            @Override
            public void run() {
                try {
                    String log = mLogFormat.format(new Date()) + " D" + "/" + tag + ":" + message + "\n";
                    writeToLogFile(log);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    public void v(final String tag, final String message) {
        mLogHandler.post(new Runnable() {
            @Override
            public void run() {
                try {
                    String log = mLogFormat.format(new Date()) + " V" + "/" + tag + ":" + message + "\n";
                    writeToLogFile(log);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    public void e(final String tag, final String message) {
        mLogHandler.post(new Runnable() {
            @Override
            public void run() {
                try {
                    String log = mLogFormat.format(new Date()) + " E" + "/" + tag + ":" + message + "\n";
                    writeToLogFile(log);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    public void i(final String tag, final String message) {
        mLogHandler.post(new Runnable() {
            @Override
            public void run() {
                try {
                    String log = mLogFormat.format(new Date()) + " I" + "/" + tag + ":" + message + "\n";
                    writeToLogFile(log);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    public void w(final String tag, final String message) {
        mLogHandler.post(new Runnable() {
            @Override
            public void run() {
                try {
                    String log = mLogFormat.format(new Date()) + " W" + "/" + tag + ":" + message + "\n";
                    writeToLogFile(log);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        });
    }

}
